#ifndef __Y64_INTERRUPT_H__
#define __Y64_INTERRUPT_H__

#include "ptrace.h"

/* 8259A中断控制器，多核处理器出现之前，是pc机使用最为普遍的中断控制器，一般采用两片8259A芯片级联的方式使用
   主8259A芯片的I/O端口地址为0x20和0x21，从8259A芯片的I/O端口是0xa0和0xa1

                                        _____________________                   _________________
                                        |                   |                   |               |
        时钟        IRQ0            --->|IR0                |                   |               |
        键盘        IRQ1            --->|IR1            INT |------------------>|INTR           |
        级联从片    IRQ2        |------>|IR2                |                   |               |
        串行口2     IRQ3        |   --->|IR3    8259A       |                   |      CPU      |
        串行口1     IRQ4        |   --->|IR4    主芯片      |                   |               |
        并行口2     IRQ5        |   --->|IR5                |     数据D7-D0     |               |
        软盘        IRQ6        |   --->|IR6                |<--------|-------->|               |
        并行口1     IRQ7        |   --->|IR7                |         |         |_______________|
                                |       |___________________|         |  
                                |                                     |  
                                |-------------------------------|     |
                                        _____________________   |     |
        实时钟      IRQ8            --->|IR0                |   |     |
        重定向IRQ2  IRQ9            --->|IR1            INT |---|     |
        保留        IRQ10           --->|IR2                |         |
        保留        IRQ11           --->|IR3    8259A       |         |
        PS2鼠标     IRQ12           --->|IR4    从芯片      |         |
        协处理器    IR13            --->|IR5                |         |
        硬盘1       IR14            --->|IR6                |<--------|
        硬盘2       IR15            --->|IR7                |
                                        |___________________|

寄存器说明：
    IRR(Interrupt Request Register，中断请求寄存器)：用来保存IR0~IR7引脚上接收的中断请求，8bit分别对应8个引脚
    IMR(Interrupt Mask Register，中断屏蔽寄存器)：用于记录屏蔽的外部引脚，同样8bit对应8个引脚，被屏蔽的引脚的请求信号不予处理
    PR(Priority Resolver，优先级解析器)：将从IRR寄存器接收的中断请求中选取最高优先级者，将其发往ISR
    ISR(In-Service Register，正在服务寄存器)：记录着正在处理的中断请求，同时8259A芯片会向cpu发送一个INT信号
    接收到中断请求信号，处理器将不在继续执行指令，转而向8259A芯片发送一个INTA来应答中断请求信号，8259A芯片收到这个应答信号后，便会把这个中断请求保存到ISR中，与此同时，复位IRR寄存器中的对应中断请求信号，以表示中断正在处理。
    随后，cpu还会向8259A芯片发送第二个INTA脉冲信号，通知8259A芯片发送中断向量号，然后8259A芯片会把中断向量号（8位数据）发送到数据总线上供cpu读取
    ICW寄存器组：(ICW1映射到0x20或0xa0，其它映射到0x21或0xa1)
        ICW1:   5~7     对于PC机，该位必须为0
                4       对于ICW，该位必须为1
                3       触发模式，现已忽略，必须为0
                2       忽略，必须为0
                1       1=单片8259A，0=级联8259A\
                0       1=使用ICW4，0=不使用ICW4
        ICW2:   3~7     中断向量号，通常情况下，主8259A的中断向量号设置为0x20(占用0x20~0x27)，从8259A的中断向量号设置为0x28(占用0x28~0x2f)
                0~2     0
        主ICW3: 7       1=IR7级联从芯片，0=无从芯片
                6       1=IR6级联从芯片，0=无从芯片
                5       1=IR5级联从芯片，0=无从芯片
                4       1=IR4级联从芯片，0=无从芯片
                3       1=IR3级联从芯片，0=无从芯片
                2       1=IR2级联从芯片，0=无从芯片（上图中该位置1）
                1       1=IR1级联从芯片，0=无从芯片
                0       1=IR0级联从芯片，0=无从芯片
        从ICW3: 3~7     必须为0
                0~2     从芯片连接到主芯片的IR引脚号（上图中引脚号为0x2）
        ICW4:   5~7     恒为0
                4       1=SFNM模式，0=FNM模式
                3,2     缓冲模式：00=无缓冲模式，10=从芯片缓冲模式，11=主芯片缓冲模式
                1       1=AEOI模式，0=EOI模式
                0       1=8086/88模式，0=MCS 80/85模式
                说明：AEOI模式：此模式可使中断控制器收到CPU发送来的第2个INTA中断响应信号后，自动复位ISR寄存器的对应位
                      EOI模式：此模式下，处理器执行完中断处理程序后，必须手动向中断控制器发送中断结束EOI指令，来复位ISR寄存器的对应位
                      FNM(Fully Nested Mode,全嵌套模式)：此模式下，中断请求的优先级按引脚名从高到低依次为IR0~IR7，如果从8259A芯片的中断请求正在被处理，那么该从芯片将被主芯片屏蔽直到处理结束，即使从芯片产生更高优先级的中断请求也不会被执行
                      SFNM(Special Fully Nested Mode，特殊全嵌套模式)：与FNM基本相同，不同点是当从芯片的中断正被处理时，主芯片不会屏蔽该从芯片，使得主芯片可以接收来自从芯片的更高优先级中断请求。
    OCW寄存器组：（OCW1映射到0x21或0xa1，OCW2和OCW3映射到0x20或0xa0）
        OCW1:   7       1=屏蔽IRQ7中断请求，0=允许IRQ7中断请求
                6       1=屏蔽IRQ6中断请求，0=允许IRQ6中断请求
                5       1=屏蔽IRQ5中断请求，0=允许IRQ5中断请求
                4       1=屏蔽IRQ4中断请求，0=允许IRQ4中断请求
                3       1=屏蔽IRQ3中断请求，0=允许IRQ3中断请求
                2       1=屏蔽IRQ2中断请求，0=允许IRQ2中断请求
                1       1=屏蔽IRQ1中断请求，0=允许IRQ1中断请求
                0       1=屏蔽IRQ0中断请求，0=允许IRQ0中断请求
        OCW2:   7       优先级循环状态
                6       特殊设定标志
                5       非自动结束标志  5~7组合值有多种含义:000-循环AEOI模式（清除）001-非特殊EOI命令（全嵌套方式）010-无操作 011-特殊EOI命令（非全嵌套方式） 100-循环AEOI模式（设置） 101-循环非特殊EOI命令 110-设置优先级命令 111-循环特殊EOI命令
                4       恒为0
                3       恒为0
                0~2     优先级设定
        OCW3:   7       恒为0
                6,5     特殊屏蔽模式：11=开启特殊屏蔽，10=关闭特殊屏蔽
                4       恒为0
                3       恒为1
                2       1=轮询，0=无查询
                1,0     10=读IRR寄存器，11=读ISR寄存器
*/

/*
8259A PIC无法满足多核处理器，只能将中断请求信号投递给一个指定的处理器，因此APIC诞生了，采用总线方式通信，将原本单个中断控制器拆分为处理器内部(每个处理器核心都有)的Local APIC和位于主板芯片组中的I/O APIC
Local APIC：既可以接收来自处理器核心的中断请求，也可以接收内部中断源和外部I/O APIC的中断请求
        寄存器地址映射表：(物理基地址由MSR寄存器组中IA32_APIC_BASE寄存器控制，默认为fee00000h, bit8指示当前处理器为引导处理器，bit10控制x2APIC模式的开启与关闭, bit11控制APIC和xAPIC模式的开启与关闭，bit12~M配置寄存器的物理基地址)
                物理地址                MSR地址                 寄存器名                        读写权限
                fee0 0000h              无                      保留                            N/A
                fee0 0010h              无                      保留                            N/A
                fee0 0020h              802h                    Local APIC ID寄存器             读写            早期Pentium和P6使用bit[27:24],Pentium 4和Xeon处理器使用bit[31:24]，x2APIC版本后bit[31:0]
                fee0 0030h              803h                    Local APIC版本寄存器            只读            31:25保留, 24指示Local APIC是否支持禁止广播EOI消息功能, 23:16此数值加1代表处理器支持的LVT表项数, 7:0代表Local APIC的版本ID(0?h表示外部APIC芯片，1?h表示内部APIC芯片)
                fee0 0040h              无                      保留                            N/A
                fee0 0050h              无                      保留                            N/A
                fee0 0060h              无                      保留                            N/A
                fee0 0070h              无                      保留                            N/A
                fee0 0080h              808h                    任务优先级寄存器TPR             读写
                fee0 0090h              无                      优先级仲裁寄存器APR             只读
                fee0 00a0h              80ah                    处理器优先级寄存器PPR           只读
                fee0 00b0h              80bh                    EOI寄存器                       只写
                fee0 00c0h              无                      远程读取寄存器RRD               只读
                fee0 00d0h              80dh                    逻辑目标寄存器LDR               读写
                fee0 00e0h              无                      目标格式寄存器DFR               读写
                fee0 00f0h              80fh                    伪中断向量寄存器SVR             读写            bit12:禁止广播EOI消息（0-关闭，1-开启）bit9:焦点处理器检测标志，bit8:APIC软件使能标志位，bit7~0:伪中断向量号
                fee0 0100h              810h                    ISR寄存器（bit 31:0）           只读
                fee0 0110h              811h                    ISR寄存器（bit 63:32）          只读
                fee0 0120h              812h                    ISR寄存器（bit 95:64）          只读
                fee0 0130h              813h                    ISR寄存器（bit 127:96）         只读
                fee0 0140h              814h                    ISR寄存器（bit 159:128）        只读
                fee0 0150h              815h                    ISR寄存器（bit 191:160）        只读
                fee0 0160h              816h                    ISR寄存器（bit 223:192）        只读
                fee0 0170h              817h                    ISR寄存器（bit 255:224）        只读
                fee0 0180h              818h                    TMR寄存器（bit 31:0）           只读
                fee0 0190h              819h                    TMR寄存器（bit 63:32）          只读
                fee0 01a0h              81ah                    TMR寄存器（bit 95:64）          只读
                fee0 01b0h              81bh                    TMR寄存器（bit 127:96）         只读
                fee0 01c0h              81ch                    TMR寄存器（bit 159:128）        只读
                fee0 01d0h              81dh                    TMR寄存器（bit 191:160）        只读
                fee0 01e0h              81eh                    TMR寄存器（bit 223:192）        只读
                fee0 01f0h              81fh                    TMR寄存器（bit 255:224）        只读
                fee0 0200h              820h                    IRR寄存器（bit 31:0）           只读
                fee0 0210h              821h                    IRR寄存器（bit 63:32）          只读
                fee0 0220h              822h                    IRR寄存器（bit 95:64）          只读
                fee0 0230h              823h                    IRR寄存器（bit 127:96）         只读
                fee0 0240h              824h                    IRR寄存器（bit 159:128）        只读
                fee0 0250h              825h                    IRR寄存器（bit 191:160）        只读
                fee0 0260h              826h                    IRR寄存器（bit 223:192）        只读
                fee0 0270h              827h                    IRR寄存器（bit 255:224）        只读
                fee0 0280h              828h                    ESR（错误状态寄存器）           只读    bit0:发送校验和错误；bit1:接收校验和错误；bit2:发送中断消息受理错误；bit3:接收中断消息受理错误；bit4:IPI无法正确定向；bit5:发送的中断向量号不合法；bit6:收到的中断向量号不合法；bit7寄存器地址不合法
                fee0 0280h~fee0 02e0h   无                      保留                            N/A
                fee0 02f0h              82fh                    LVT CMCI寄存器                  读写
                fee0 0300h              830h                    中断命令寄存器ICR（bit 31:0）   读写
                fee0 0310h              830h                    中断命令寄存器ICR（bit 63:32）  读写
                fee0 0320h              832h                    LVT定时器寄存器                 读写
                fee0 0330h              833h                    LVT温度传感器寄存器             读写
                fee0 0340h              834h                    LVT性能监控计数寄存器           读写
                fee0 0350h              835h                    LVT LINT0寄存器                 读写
                fee0 0360h              836h                    LVT LINT1寄存器                 读写
                fee0 0370h              837h                    LVT错误寄存器                   读写
                fee0 0380h              838h                    初始计数寄存器（定时器专用）    读写
                fee0 0390h              839h                    当前计数寄存器（定时器专用）    只读
                fee0 03a0h~fee0 03d0h   无                      保留                            N/A
                fee0 03e0h              83eh                    分频配置寄存器（定时器专用）    读写
                N/A                     83fh                    SELF IPI寄存器                  只写


I/O APIC: 主要接收外部I/O设备发送来的中断请求，能够提供一种机制来分发外部中断请求至目标处理器的Local APIC中
        寄存器地址映射表：通过OIC寄存器配置间接访问寄存器的物理地址，默认xy=00
                物理地址                名称                    位宽                            访问权限
                FECxy000h               间接索引寄存器          8                               读写            低8位用来索引I/O APIC寄存器
                FECxy010h               数据操作寄存器          32                              读写            用于读写目标I/O APIC寄存器内的数据
                FECxy040h               EOI寄存器               32                              只写            采用电平触发模式的中断请求，在中断处理结束时必须通过EOI寄存器向I/O APIC发送EOI消息
        I/O APIC寄存器，通过上面寄存器通过索引间接访问
                索引值                  名称                    位宽                            访问权限
                00h                     I/O APIC ID寄存器       32                              读写            bit[27:24]有效，处理器必须保证APIC总线上APIC设备都有唯一的ID值
                01h                     I/O APIC 版本寄存器     32                              只读
                02h~0fh                 保留                    -                               只读
                10h~11h                 I/O中断定向投递寄存器0  64                              读写
                12h~13h                 I/O中断定向投递寄存器1  64                              读写
                ...                     ...                     ...                             ...
                3eh~3fh                 I/O中断定向投递寄存器23 64                              读写
                40h~ffh                 保留                    -                               只读
*/

typedef struct {
    void (*enable)(unsigned long irq);          // 使能中断操作函数
    void (*disable)(unsigned long irq);         // 禁止中断操作函数
    unsigned long (*install)(unsigned long irq, void *arg);     // 安装中断操作函数
    void (*uninstall)(unsigned long irq);       // 卸载中断操作函数
    void (*ack)(unsigned long irq);             // 应答中断操作函数
} st_hw_int_type;

typedef struct {
    st_hw_int_type *controller;     // 中断使能、禁止、应答等相关操作函数
    char *irq_name;                 // 中断名称
    unsigned long param;            // 中断处理函数的参数
    void (*handler)(unsigned long nr, unsigned long param, st_pt_regs *regs);   // 中断处理函数
    unsigned long flags;            // 自定义标志位
} st_irq_desc;

#define NR_IRQS 24

extern st_irq_desc g_intr_desc[NR_IRQS];

extern void (*g_interrupt[24])(void);

int register_irq(unsigned long irq, void *arg, void (*handler)(unsigned long nr, unsigned long param, st_pt_regs *regs), unsigned long param, st_hw_int_type *controller, char *irq_name);

int unregister_irq(unsigned long irq);

#endif